# 表单双向绑定—v-model

# input

可用于<input>,<select>, 或 <textarea> 元素!

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Title</title>
  </head>

  <body>
    <div id="app"><input type="text" v-model="message" />{{message}}</div>

    <script src="/lib/vue.js"></script>
    <script>
      const vm = new Vue({
        el: "#app",
        data: {
          message: "Hello",
        },
      });
    </script>
  </body>
</html>

注意:当一个 <input>,<select>, 或 <textarea> 元素的 value 被修改时,会触发 input 事件。

每当元素的 value 改变,input 事件都会被触发。这与 change 事件不同。change 事件仅当 value 被提交时触发,如按回车键,从一个 options 列表中选择一个值等。

V-model 可以用如下实现

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Title</title>
  </head>

  <body>
    <div id="app">
      <input type="text" v-model="message" />
      <h2>{{message}}</h2>
      <input type="text" :value="message" @input="valueChange" />
      <input
        type="text"
        :value="message"
        @input="message = $event.target.value"
      />
    </div>

    <script src="/lib/vue.js"></script>
    <script>
      const vm = new Vue({
        el: "#app",
        data: {
          message: "Hello",
        },
        methods: {
          valueChange(event) {
            this.message = event.target.value;
          },
        },
      });
    </script>
  </body>
</html>

# radio

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Title</title>
  </head>

  <body>
    <div id="app">
      <label for="male"></label>
      <input type="radio" name="sex" id="male" value="" v-model="sex" />
      <label for="female"></label>
      <input type="radio" name="sex" id="female" value="" v-model="sex" />
      <!-- 此时name可以省略 -->
      <br />
      <h2>性别:{{sex}}</h2>
    </div>

    <script src="/lib/vue.js"></script>
    <script>
      const vm = new Vue({
        el: "#app",
        data: {
          message: "Hello",
          sex: "女",
        },
        methods: {},
      });
    </script>
  </body>
</html>

# 单个 & 多个 checkbox & 实际开发

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Title</title>
  </head>

  <body>
    <div id="app">
      <!-- 单个 -->
      <label for="agree">同意协议</label>
      <input type="checkbox" name="agree" id="agree" v-model="agree" />
      <!-- name 可以省略 -->
      <button :disabled="!agree">下一步</button>
      <br />
      <h2>{{agree}}</h2>

      <hr />

      <!-- 多个 -->
      <input
        type="checkbox"
        name="hobby"
        id="hobby"
        v-model="hobby"
        value=""
      /><input
        type="checkbox"
        name="hobby"
        id="hobby"
        v-model="hobby"
        value=""
      /><input
        type="checkbox"
        name="hobby"
        id="hobby"
        v-model="hobby"
        value="篮球"
      />篮球
      <!-- name 可以省略 -->
      <br />
      <h2>{{hobby}}</h2>
      <hr />

      <!-- 真实开发 -->
      <label v-for="(item,index) in originHobbies" :for="item">
        <input
          type="checkbox"
          :id="item"
          name="selectedHobbies"
          :value="item"
          v-model="selectedHobbies"
        />{{item}}
      </label>
      <h2>{{selectedHobbies}}</h2>
    </div>

    <script src="/lib/vue.js"></script>
    <script>
      const vm = new Vue({
        el: "#app",
        data: {
          agree: false,
          hobby: [],
          // 真实开发
          originHobbies: ["唱", "跳", "篮球", "rap"],
          selectedHobbies: [],
        },
      });
    </script>
  </body>
</html>

# 单选 & 多选 select

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Title</title>
  </head>

  <body>
    <div id="app">
      <select name="hobby" id="hobby" v-model="hobby">
        <option value=""></option>
        <option value=""></option>
        <option value="篮球">篮球</option>
      </select>
      <h2>{{hobby}}</h2>
      <hr />

      <select name="hobbies" id="hobbies" v-model="hobbies" multiple>
        <option value=""></option>
        <option value=""></option>
        <option value="篮球">篮球</option>
        <option value="rap">rap</option>
      </select>
      <h2>{{hobbies}}</h2>
    </div>

    <script src="/lib/vue.js"></script>
    <script>
      const vm = new Vue({
        el: "#app",
        data: {
          hobby: "篮球",
          hobbies: [],
        },
        methods: {},
      });
    </script>
  </body>
</html>

# 修饰符

# .lazy

在默认情况下,v-model 在每次 input 事件触发后将输入框的值与数据进行同步 (除了上述输入法组合文字时)。你可以添加 lazy 修饰符,从而转为change 事件之后进行同步,如失去焦点或回车后

# .number

如果想自动将用户的输入值转为数值类型,可以给 v-model 添加 number 修饰符。这通常很有用,因为即使在 type="number" 时,HTML 输入元素的值也总会返回字符串。如果这个值无法被 parseFloat() 解析,则会返回原始的值。

# .trim

如果要自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Title</title>
  </head>

  <body>
    <div id="app">
      <input type="text" v-model.lazy="username" />{{username}}
      <hr />
      <input type="number" v-model.number="age" />{{age}} {{typeof age}}
      <hr />
      <input type="text" v-model.trim="name" />{{name}}
    </div>

    <script src="/lib/vue.js"></script>
    <script>
      const vm = new Vue({
        el: "#app",
        data: {
          username: "Hello",
          age: 0,
          name: "",
        },
        methods: {},
      });
    </script>
  </body>
</html>